/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: Frank
 * 系统版本: 1.0.0
 * 开发人员: Frank
 * 开发时间: 2019/11/20 9:15
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.spring.arch.message.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.spring.arch.common.dto.result.ResultDTO;
import com.spring.arch.common.exception.ExceptionHolder;
import com.spring.arch.message.common.errorcode.MessageErrorCode;
import com.spring.arch.message.common.sender.sms.SmsResult;
import com.spring.arch.message.common.sender.sms.SmsSender;
import com.spring.arch.message.dto.VerificationCheckParam;
import com.spring.arch.message.dto.VerificationSendParam;
import com.spring.arch.message.enums.BusinessType;
import com.spring.arch.common.dto.result.ResultDTO;
import com.spring.arch.common.exception.ExceptionHolder;
import com.spring.arch.message.common.config.MessageCacheConfiguration;
import com.spring.arch.message.common.sender.sms.SmsResult;
import com.spring.arch.message.common.sender.sms.SmsSender;
import com.spring.arch.message.dto.VerificationCheckParam;
import com.spring.arch.message.dto.VerificationSendParam;
import com.spring.arch.message.enums.BusinessType;
import com.spring.arch.message.model.SmsTemplateConfig;
import com.spring.arch.message.repository.SmsTemplateConfigRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static com.spring.arch.message.common.errorcode.MessageErrorCode.E1016000101;
import static com.spring.arch.message.common.errorcode.MessageErrorCode.E1016000103;

/**
 * Web端短信基础业务控制器
 *
 * @author Frank
 * @version 1.0.0.1
 * @since 2019-11-19 14:02:38
 */
@Slf4j
@RestController
@RequestMapping(value = "/message/verification", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Api(tags = {"验证码管理API"}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class VerificationController {

    @Qualifier(MessageCacheConfiguration.VERIFICATION_CACHE)
    @Autowired
    private Map<String, String> verificationCache;

    @Autowired
    private SmsSender smsSender;
    @Autowired
    private SmsTemplateConfigRepository smsTemplateConfigRepository;

    /**
     * 发送验证码
     */
    @ApiOperation(value = "发送验证码")
    @PostMapping(value = "send")
    public ResultDTO<Void> sendVerificationCode(@RequestBody @Valid VerificationSendParam param) {
        final String mobile = param.getMobile();
        final BusinessType businessType = param.getBusinessType();
        // 获取短信模板
        String templateCode = getTemplateCode(businessType);
        if (StringUtils.isBlank(templateCode)) {
            log.error("获取短信模板为空，businessType={}", businessType);
            throw ExceptionHolder.serviceException(MessageErrorCode.E1016000101, businessType.toString());
        }

        // 生成验证码
        String random = RandomStringUtils.randomNumeric(6);
        // 构造模板参数
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", random);
        // 发送短信
        SmsResult smsResult = smsSender.sendSms(templateCode, JSON.toJSONString(jsonObject), mobile);
        if (smsResult.isSuccess()) {
            // 设置缓存
            verificationCache.put(businessType + "_" + mobile, random);
            log.error("发送验证码|短信发送成功，param={}, result={}", param, smsResult.getMsg());
        } else {
            log.error("发送验证码|短信发送失败，param={}, result={}", param, smsResult.getMsg());
        }
        return ResultDTO.success();
    }

    /**
     * 验证验证码
     */
    @ApiOperation(value = "验证验证码")
    @PostMapping(value = "check")
    public ResultDTO<Void> checkVerificationCode(@RequestBody @Valid VerificationCheckParam param) {
        final String mobile = param.getMobile();
        final BusinessType businessType = param.getBusinessType();
        final String code = param.getCode();
        // 获取验证码缓存
        String cacheCode = verificationCache.get(businessType + "_" + mobile);
        if (!Objects.equals(code, cacheCode)) {
            log.error("验证验证码|短信验证码错误或失效，param={}, cacheCode={}", param, cacheCode);
            throw ExceptionHolder.serviceException(MessageErrorCode.E1016000103);
        }
        // 清除验证码缓存
        verificationCache.remove(businessType + "_" + mobile);
        log.info("验证验证码|短信验证码成功，param={}, cacheCode={}", param, cacheCode);
        return ResultDTO.success();
    }

    /**
     * 根据业务类型获取模板编码
     * @param businessType 业务类型
     * @return 模板编码
     */
    private String getTemplateCode(BusinessType businessType) {
        Optional<SmsTemplateConfig> optional = smsTemplateConfigRepository.findByBusinessType(businessType);
        return optional.map(SmsTemplateConfig::getTemplateCode).orElse(null);
    }
}
